import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.management.Query;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;

import processing.core.PApplet;
import processing.core.PFont;
import processing.core.PImage;


public class SongDisplayApplet extends PApplet implements TLModule{

	private static final double CHART_ENTRIES = 100;
	private Long song = 1640L;
	private boolean change = true;
	private Timestamp startTime;
	private Timestamp endTime;
	private Connection connection;
	private PImage background;
	private PFont font;
	private PImage halfCircle;
	private String billboard;
	private long MAX_TWEETS = 74285;

	public void setup(){
		loadDatabase();
		change = true;
		size(450, 250);
		background(255);
		background = loadImage("display.png");
		image(background, 0,0, 400, 160);
		halfCircle = loadImage("half_circle.png");
		font = createFont("calibri", 22);
		textFont(font, 20);
		song = 1639L;
		billboard = "hot-100";
		startTime = new Timestamp(1271714400000L);
		endTime = new Timestamp(1272319200000L);
		
		
	}

	public void draw(){
		if(change){
			image(background, 0,0, 400, 160);
			displaySongInfo();
			change = false;
		}

	}

	private void displaySongInfo() {
		List<Map<String, Object>> infos = getSongInfo();
		
		Map<String, Object> info = getCorrectBillboard(infos);	
		
		String songName = (String) info.get("song_title");
		String songArtist = (String) info.get("artist_name");
		
		Object billboardRank = (Object) info.get("billboard_ranking");
		long tweetNr = ((BigDecimal) info.get("twitter_popularity")).longValue();
		
		long twitterRank = MAX_TWEETS - tweetNr + 1;

		fill(255);
		
		text("SONG: ", 40, 50);
		fill(0);
		text(songName);
		fill(255);
		text("ARTIST: ", 40, 75);
		fill(0);
		text(songArtist);
		fill(255);
		text("BILLBOARD CHART: ", 40,100);
		fill(0);
		text(String.valueOf(billboardRank));
		fill(255);
		text("NO. TWEETS: ", 40,125);
		fill(0);
		text(String.valueOf(tweetNr));
		
		drawHeatCircle(twitterRank);
		


	}

	private Map<String, Object> getCorrectBillboard(List<Map<String, Object>> info) {
		Map<String, Object> correctMap = null;
		if(info.isEmpty()){
			correctMap = new HashMap<String, Object>();
			correctMap.put("billboard_ranking", "?");
			correctMap.put("song_title", "?");
			correctMap.put("artist_name", "?");
			correctMap.put("twitter_popularity", new BigDecimal(0));
			
		}
		for(Map<String, Object> map : info){
			if(map.get("chart_name").equals(billboard)){
				correctMap = map;
				break;				
			}
			
		}
		if(correctMap == null){
			correctMap = info.get(0);
			correctMap.put("billboard_ranking", "?");
		}
		
		return correctMap;
	}

	private void drawHeatCircle(long twitterRank) {
		int blue = (int)((double)twitterRank / (double)MAX_TWEETS * 255);
		int red = 255 - blue;	
		int green = (int) ((double)blue/255D * 148);
		tint(red, green, blue);
		image(halfCircle, 0,0, 400, 160);
		noTint();
		
		
	}

	private List<Map<String, Object>> getSongInfo() {
		String sql = "SELECT chart_name, t2.artist_name, ranking as billboard_ranking, t2.twitter_popularity, t2.song_title FROM ranking," +
				"(SELECT *, SUM(nr_tweets) as twitter_popularity FROM song_popularity," +
				"(SELECT song.song_title as song_title2, song.artist_name " +
				"FROM song " +
				"WHERE song_id = ?) t1 " +
				"WHERE song_popularity.song_title = t1.song_title2" +
				" AND song_popularity.date BETWEEN ? AND ? " +
				") t2 " +
				"WHERE ranking.song_title = t2.song_title " +
				"AND ranking.chart_date BETWEEN ? AND ?";
		
		QueryRunner qr = new QueryRunner();
		ResultSetHandler rsh = new MapListHandler();

		Object[] params = new Object[]{song, startTime, endTime, startTime, endTime};
		List<Map<String, Object>> result = null;
		try {
			result = (List<Map<String, Object>>) qr.query(connection, sql, params, rsh);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;

	}

	@Override
	public void highlightPhrase(List<Long> phraseId) {
		// TODO Auto-generated method stub

	}

	@Override
	public void highlightSong(List<Long> songId) {
		// TODO Auto-generated method stub

	}

	@Override
	public void highlightUser(List<String> users) {
		// TODO Auto-generated method stub

	}

	@Override
	public void reset() {
		resetSong();
		resetTime();

	}

	@Override
	public void resetPhrase() {
		// TODO Auto-generated method stub

	}

	@Override
	public void resetSong() {
		song = null;

	}

	@Override
	public void resetTime() {
		startTime = null;
		endTime = null;

	}

	@Override
	public void resetUser() {
		// TODO Auto-generated method stub

	}

	@Override
	public void setPhrase(List<Long> phraseId) {
		// TODO Auto-generated method stub

	}

	@Override
	public void setSong(List<Long> songId) {
		song = songId.get(0);
		change = true;
		//song = 573L;

	}

	@Override
	public void setTimeSpan(Timestamp start, Timestamp end) {
		startTime = start;
		endTime = end; 
	}

	@Override
	public void setUser(List<String> users) {
		// TODO Auto-generated method stub

	}

	private void loadDatabase() {
		connection = null;
		try {
			// Load the JDBC driver
			String driverName = "org.gjt.mm.mysql.Driver"; // MySQL MM JDBC driver
			Class.forName(driverName);

			// Create a connection to the database
	//		String serverName = "djura.crabdance.com";
	String serverName = "localhost";
			String mydatabase = "infviz";
			String url = "jdbc:mysql://" + serverName + "/" + mydatabase; // a JDBC url
			String username = "root";
			String password = "augmented";
			connection = DriverManager.getConnection(url, username, password);
		} catch (ClassNotFoundException e) {
			// Could not find the database driver
		} catch (SQLException e) {
			// Could not connect to the database
		} 

	}

	@Override
	public void resetBillBoard(String chartName) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setBillBoard(String chartName) {
		billboard = chartName;
		change = true;
		
	}

}
